//
// Created by fazhehy on 2024/2/26.
//

#include "nrf24l01.h"
#include <string.h>
#include "common_inc.h"


static void nrf24l01_spi_delay()
{
    __NOP();
    __NOP();
    __NOP();
    __NOP();
}

uint8_t nrf24l01_spi_read_write(uint8_t data)
{
    uint8_t result = 0;
    for (uint8_t i = 0; i < 8; ++i) {

        if (0x80 & data){
            NRF24L01_MOSI_OUT_H();
        }
        else{
            NRF24L01_MOSI_OUT_L();
        }
        nrf24l01_spi_delay();
        NRF24L01_SCK_OUT_H();
        data <<= 1;
        result <<= 1;
        if (NRF24L01_MISO_IN())
            result |= 0x01;
        nrf24l01_spi_delay();
        NRF24L01_SCK_OUT_L();
    }
    return result;
}

static uint8_t nrf24l01_write_reg(uint8_t reg, uint8_t data)
{
    uint8_t status;
    NRF24L01_CSN_OUT_L();
    status = nrf24l01_spi_read_write(reg);
    nrf24l01_spi_read_write(data);
    NRF24L01_CSN_OUT_H();
    return status;
}

static uint8_t nrf24l01_read_reg(uint8_t reg)
{
    uint8_t status;
    NRF24L01_CSN_OUT_L();
     nrf24l01_spi_read_write(reg);
    status = nrf24l01_spi_read_write(0);
    NRF24L01_CSN_OUT_H();
    return status;
}

static uint8_t nrf24l01_read_buf(uint8_t reg, uint8_t * buffer, uint8_t len)
{
    uint8_t  status;
    NRF24L01_CSN_OUT_L();
    status = nrf24l01_spi_read_write(reg);
    for (int i = 0; i < len; ++i) {
        buffer[i] = nrf24l01_spi_read_write(0);
    }
    NRF24L01_CSN_OUT_H();
    return status;
}

static uint8_t nrf24l01_write_buf(uint8_t reg, uint8_t * buffer, uint8_t len)
{
    uint8_t status;
    NRF24L01_CSN_OUT_L();
    status = nrf24l01_spi_read_write(reg);
    for (int i = 0; i < len; ++i) {
        nrf24l01_spi_read_write(buffer[i]);
    }
    NRF24L01_CSN_OUT_H();
    return status;
}

uint8_t nrf24l01_check()
{
    NRF24L01_CSN_OUT_H();
    NRF24L01_CE_OUT_L();
    NRF24L01_SCK_OUT_L();

    uint8_t buffer[] = {0xa5, 0xa5, 0xa5, 0xa5, 0xa5};
    nrf24l01_write_buf(NRF24L01_WRITE_REG+NRF24L01_TX_ADDR, buffer, 5);
    memset(buffer, 0, 5);
    nrf24l01_read_buf(NRF24L01_TX_ADDR, buffer, 5);
    int i = 0;
    for (; i < 5; ++i) {
        if (buffer[i] != 0xa5)
            break;
    }
    if (i != 5)
        return 1;
    return 0;
}

const uint8_t ADDRESS[NRF24L01_TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
void nrf24l01_init()
{
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_SETUP_AW, NRF24L01_RX_ADR_WIDTH);
    nrf24l01_write_buf(NRF24L01_WRITE_REG+NRF24L01_TX_ADDR, (uint8_t *)ADDRESS, NRF24L01_TX_ADR_WIDTH);//写TX节点地址
    nrf24l01_write_buf(NRF24L01_WRITE_REG+NRF24L01_RX_ADDR_P0, (uint8_t *)ADDRESS, NRF24L01_RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_EN_AA,0x01);     //使能通道0的自动应答
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_EN_RXADDR,0x01); //使能通道0的接收地址
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_RF_CH,40);       //设置RF通道为40
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_RX_PW_P0,NRF24L01_RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
}

uint8_t nrf24l01_send_buffer(uint8_t * buffer)
{
    uint8_t status;

    NRF24L01_CE_OUT_L();
    nrf24l01_write_buf(NRF24L01_WR_TX_PLOAD, buffer, NRF24L01_TX_PLOAD_WIDTH);
    NRF24L01_CE_OUT_H();
    while (NRF24L01_IRQ_IN() != 0);
    status = nrf24l01_read_reg(NRF24L01_STATUS);
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_STATUS, status);
    if (status & NRF24L01_MAX_TX){
        nrf24l01_write_reg(NRF24L01_FLUSH_TX, 0xff);
        return NRF24L01_MAX_TX;
    }
    if (status & NRF24L01_TX_OK){
        return NRF24L01_TX_OK;
    }
    return 0xff;
}

uint8_t nrf24l01_receive_buffer(uint8_t * buffer)
{
    uint8_t status;
    status = nrf24l01_read_reg(NRF24L01_STATUS);
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_STATUS, status);
    if (status & NRF24L01_RX_OK){
        nrf24l01_read_buf(NRF24L01_RD_RX_PLOAD, buffer, NRF24L01_RX_PLOAD_WIDTH);
        nrf24l01_write_reg(NRF24L01_FLUSH_RX, 0xff);
        return 0;
    }
    return 1;
}

void nrf24l01_set_rx_mode()
{
    NRF24L01_CE_OUT_L();
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
    nrf24l01_write_reg(NRF24L01_FLUSH_RX,0xff);//清除RX FIFO寄存器
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_STATUS, 0xff);
    NRF24L01_CE_OUT_H();
}

void nrf24l01_set_tx_mode()
{
    NRF24L01_CE_OUT_L();
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
}

uint8_t receive_buffer[32];
uint8_t receive_flag = 0;
uint8_t irq = 0;
void nrf24l01_receive_callback(uint16_t GPIO_Pin)
{
    uint8_t status;
    irq = 0;
    if (GPIO_Pin == NRF24L01_IRQ_PIN){
        NRF24L01_CE_OUT_L();
        status = nrf24l01_read_reg(NRF24L01_STATUS);
        nrf24l01_write_reg(NRF24L01_WRITE_REG + NRF24L01_STATUS, status);
        if (status & NRF24L01_RX_OK) {
            nrf24l01_read_buf(NRF24L01_RD_RX_PLOAD, receive_buffer, NRF24L01_RX_PLOAD_WIDTH);
            nrf24l01_write_reg(NRF24L01_FLUSH_RX, 0xff);
//            receive_flag = 1;
            protocol_analysis();
        }
        nrf24l01_write_reg(NRF24L01_FLUSH_RX, 0xff);

        NRF24L01_CE_OUT_H();
    }
}

uint8_t transmit_buffer[32];
uint8_t transmit_flag = 0; // 1 means normal 0 means error
void nrf24l01_transmit_callback()
{
    NRF24L01_CE_OUT_L();
    nrf24l01_write_buf(NRF24L01_WR_TX_PLOAD, transmit_buffer, NRF24L01_TX_PLOAD_WIDTH);
    NRF24L01_CE_OUT_H();
    irq = 1;
    while (irq == 1){
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
//        printf("irq\n");
    }
    uint8_t status = nrf24l01_read_reg(NRF24L01_STATUS);
    nrf24l01_write_reg(NRF24L01_WRITE_REG+NRF24L01_STATUS, status);
    transmit_flag = 1;
    if (status & NRF24L01_MAX_TX){
        nrf24l01_write_reg(NRF24L01_FLUSH_TX, 0xff);
        transmit_flag = 0;
    }
}

uint8_t buffer[32];
uint8_t nrf24l01_send_data(const uint8_t * data, uint8_t len)
{
    receive_flag = 1;
    nrf24l01_set_tx_mode();
    HAL_Delay(10);
    if (len > 31)
        return 0;
    memset(buffer, 0, 32);
    buffer[0] = len;
    for (uint8_t i = 0; i < 31; ++i) {
        if (i < len)
            buffer[i+1] = data[i];
        else
            buffer[i+1] = 0;
    }
    uint8_t state = nrf24l01_send_buffer(buffer);
    nrf24l01_set_rx_mode();
    receive_flag = 0;
    return state;
}
